package util;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.lucene.analysis.standard.*;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.store.*;
import org.apache.lucene.util.Version;
/**
 *
 * @author dragonboy
 */
public class Lucene_Index {
    private static IndexWriter myIndexWriter = null;
    private static IndexWriter myFSDirIndex = null;
    private static StandardAnalyzer myAnalyzer = null;
    private static IndexWriterConfig myConfig = null;
    private static Directory myRAMDirectory = null;
    private static Searcher myIndexSearcher = null;
    private static FSDirectory my_FSDir = null;
    private static Searcher myFSDirIndexSearcher = null;
    private static String _AComment = "";

    private static void createFSDirectory(File path) throws IOException{
        if(my_FSDir == null){
            my_FSDir = FSDirectory.open(path);
        }
    }
    private static void createRAMDirectory() throws IOException{
        if(myRAMDirectory == null)
            myRAMDirectory = new RAMDirectory();
    }
    
    private static void createAnalyser() throws IOException{
        if(myAnalyzer == null){
            myAnalyzer = new StandardAnalyzer(Version.LUCENE_34);
        }
    }
    
    private static void createRAMIndexWriter() throws IOException{
        if(myIndexWriter == null){
            createRAMDirectory();
            createAnalyser();
            myConfig = new IndexWriterConfig(Version.LUCENE_34, myAnalyzer);
            myIndexWriter = new IndexWriter(myRAMDirectory, myConfig);
        }
    }
    
    private static void createFSDirIndexWriter(File path) throws IOException{
        if(myFSDirIndex == null){
            myFSDirIndex = new IndexWriter(Lucene_Index.getFSDirectory(path),
                    Lucene_Index.getAnalyzer(),
                    IndexWriter.MaxFieldLength.LIMITED);
        }
    }
    
    public static IndexWriter getFSDirIndexWriter(File path) throws IOException{
        if(Lucene_Index.myFSDirIndex == null){
            Lucene_Index.createFSDirIndexWriter(path);
        }
        return Lucene_Index.myFSDirIndex;
    }
    
    public static IndexWriter getRAMIndexWriter() throws IOException{
        if(myIndexWriter == null){
            createRAMIndexWriter();
        }
        return myIndexWriter;
    }
    
    public static FSDirectory getFSDirectory(File path) throws IOException{
        if(Lucene_Index.my_FSDir == null){
            createFSDirectory(path);
        }
        return Lucene_Index.my_FSDir;
    }
   
    private static Directory getRAMDirectory(){
        if(Lucene_Index.myRAMDirectory == null){
            myRAMDirectory = new RAMDirectory();
        }
        return Lucene_Index.myRAMDirectory;
    }
    
    private static void createIndexSearcher(){
        if(myIndexSearcher == null){
            try {
                myIndexSearcher = new IndexSearcher(Lucene_Index.getRAMDirectory(), true);
            } catch (CorruptIndexException ex) {
                Logger.getLogger(Lucene_Index.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Lucene_Index.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    private static void createIndexSearcher(File path){
        if(Lucene_Index.myFSDirIndexSearcher == null){
            try {
                myFSDirIndexSearcher = new IndexSearcher(Lucene_Index.getFSDirectory(path),true);
            } catch (IOException ex) {
                Logger.getLogger(Lucene_Index.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    public static Searcher getIndexSearcher(){
        if(Lucene_Index.myIndexSearcher == null){
            createIndexSearcher();
        }
        return myIndexSearcher;
    }
    
    public static Searcher getIndexSearcher(File path){
        if(Lucene_Index.myFSDirIndexSearcher == null){
            createIndexSearcher(path);
        }
        return myFSDirIndexSearcher;
    }
    
    public static void closeIndexWriter() throws IOException {
        if (myIndexWriter != null) {
            myIndexWriter.close();
        }
        if(Lucene_Index.myFSDirIndex!= null)
            myFSDirIndex.close();
    }
    
    
    
    public static StandardAnalyzer getAnalyzer(){
        if(Lucene_Index.myAnalyzer == null){
            try {
                createAnalyser();
            } catch (IOException ex) {
                Logger.getLogger(Lucene_Index.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return Lucene_Index.myAnalyzer;
    }
    // open an index and start file directory traversal
    public static int index(File dataDir, String prefix, String type_cmt)throws IOException {
        if (!dataDir.exists() || !dataDir.isDirectory()) {
            throw new IOException(dataDir + " does not exist or is not a directory");
        }
        indexDirectory(Lucene_Index.getRAMIndexWriter(), dataDir, prefix);
        //Directory.copy(this.getDirectory(), FSDirectory.open(indexDir), false);
        int numOfIndex = Lucene_Index.getRAMIndexWriter().numRamDocs();
        Lucene_Index.closeIndexWriter();
        return numOfIndex;
    }
    
    public static int indexFSDir(File dataDir, File indexpath, String prefix) throws IOException{
        if (!dataDir.exists() || !dataDir.isDirectory()) {
            throw new IOException(dataDir + " does not exist or is not a directory");
        }
        indexDirectory(Lucene_Index.getFSDirIndexWriter(indexpath), dataDir, prefix);
        int numOfIndex = 0;// = this.getFSDirectory(indexpath);
        return numOfIndex;
    }
   
    private static void indexDirectory(IndexWriter writer, File dir, String prefix)throws IOException {
        File[] files = dir.listFiles();
        for (int i = 0; i < files.length; i++) {
            File f = files[i];
            if (f.isDirectory()) {
                indexDirectory(writer, f, prefix);
            } else if (f.getName().startsWith(prefix)){
                //this.indexContentFile(writer, f, type_cmt);
                Lucene_Index.indexContentFile(writer, f);
            }
        }
    }
    
    public static void search(Query q, TopScoreDocCollector collector, File path){
        try {
            Lucene_Index.getIndexSearcher(path).search(q, collector);
        } catch (IOException ex) {
            Logger.getLogger(Lucene_Index.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    private static void indexFile(IndexWriter writer, File f)throws IOException {
        if (f.isHidden() || !f.exists() || !f.canRead()) {
            return;
        }
        //System.out.println("Indexing " + f.getName().subSequence(19,29).toString());
        Document doc = new Document();
        //doc.add(new Field("content", new FileReader(f)));
        doc.add(new Field("filename", f.getCanonicalPath(), Field.Store.YES, Field.Index.ANALYZED));
        writer.addDocument(doc);
    }
    private static void indexContentFile(IndexWriter writer, File f) throws IOException{
        if(f.isHidden() || !f.exists() || !f.canRead()){
            return;
        }
        //to do get comment by comment and index to lucene
        processLineByLine(writer, f);
        
    }
    private static void processLineByLine(IndexWriter writer, File fFile) throws IOException {
        //Note that FileReader is used, not File, since File is not Closeable
        String date = fFile.getName().substring(19, 29);//contentstorage.log.2011-21-12-23
        Scanner scanner = null;
        try {
            scanner = new Scanner(new FileReader(fFile));
            while ( scanner.hasNextLine() ){
                processLine(writer, scanner.nextLine(), date);
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Lucene_Index.class.getName()).log(Level.SEVERE, null, ex);
        }
        finally {
            //ensure the underlying stream is always closed
            //this only has any effect if the item passed to the Scanner
            //constructor implements Closeable (which it does in this case).
            scanner.close();
        }
    }
    
    protected static void processLine(IndexWriter writer, String aLine, String date) throws IOException{
        if(aLine.startsWith("Start")){
            return;
        }
        //if begin a line comment_log
        if(aLine.startsWith("(l190)")){
            if(_AComment.endsWith("0") || _AComment.endsWith("3") || _AComment.endsWith("4") || _AComment.endsWith("5")){
                Document doc = new Document();
                doc.add(new Field(date+"."+_AComment.substring(_AComment.length()-1), _AComment.substring(0,_AComment.length()-2), Field.Store.YES, Field.Index.ANALYZED));
                writer.addDocument(doc);
            }
            _AComment = aLine.substring(9);
        }
        //if a comment have some character "\n"
        else{
            _AComment += "\n" + aLine; 
        }
    }
}
